using System;
using dnAnalytics.LinearAlgebra;
using NUnit.Framework;

namespace dnAnalytics.Tests.LinearAlgebra
{
    [TestFixture]
    public class DenseVectorTest : VectorTest
    {
        public override Vector GetVector(int order)
        {
            return new DenseVector(order);
        }

        public override Vector GetVector(int order, double value)
        {
            return new DenseVector(order, value);
        }

        public override Vector GetVector(double[] data)
        {
            return new DenseVector(data);
        }

        public override Matrix GetMatrix(int rows, int columns)
        {
            return new DenseMatrix(rows, columns);
        }

        [Test]
        public void DenseOperatorSubtract()
        {
            DenseVector vector1 = new DenseVector(testArray);
            DenseVector vector2 = new DenseVector(testArray);
            DenseVector result = vector1 - vector2;
            Assert.AreEqual(vector1.Count, result.Count);
            for (int i = 0; i < vector1.Count; i++)
            {
                Assert.AreEqual(vector1[i] - vector2[i], result[i]);
            }
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void DenseOperatorSubtractNull1()
        {
            DenseVector vector = new DenseVector(testArray);
            DenseVector result = vector - null;
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void DenseOperatorSubtractNull2()
        {
            DenseVector vector = new DenseVector(testArray);
            DenseVector result = null - vector;
        }

        [Test]
        [ExpectedException(typeof(NotConformableException))]
        public void DenseOperatorSubtractVectorVectorNonConformable()
        {
            DenseVector vector1 = new DenseVector(testArray);
            DenseVector vector2 = new DenseVector(vector1.Count + 1);
            DenseVector result = vector1 - vector2;
        }

        [Test]
        public void DenseOperatorNegate()
        {
            DenseVector DenseVector = new DenseVector(testArray);
            DenseVector result = -DenseVector;
            Assert.AreEqual(DenseVector.Count, result.Count);
            for (int i = 0; i < DenseVector.Count; i++)
            {
                Assert.AreEqual(-DenseVector[i], result[i]);
            }
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void DenseOperatorNegateNull()
        {
            DenseVector DenseVector = null;
            DenseVector = -DenseVector;
        }

        [Test]
        public void DenseOperatorAdd()
        {
            DenseVector vector1 = new DenseVector(testArray);
            DenseVector vector2 = new DenseVector(testArray);
            DenseVector result = vector1 + vector2;
            Assert.AreEqual(vector1.Count, result.Count);
            for (int i = 0; i < vector1.Count; i++)
            {
                Assert.AreEqual(vector1[i] + vector2[i], result[i]);
            }
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void DenseOperatorAddNull1()
        {
            DenseVector vector = new DenseVector(testArray);
            DenseVector result = vector + null;
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void DenseOperatorAddNull2()
        {
            DenseVector vector2 = new DenseVector(testArray);
            DenseVector result = null + vector2;
        }

        [Test]
        [ExpectedException(typeof(NotConformableException))]
        public void DenseOperatorAddNonConformable()
        {
            DenseVector vector1 = new DenseVector(testArray);
            DenseVector vector2 = new DenseVector(vector1.Count + 1);
            DenseVector result = vector1 + vector2;
        }

        [Test]
        public void DenseOperatorPlus()
        {
            DenseVector DenseVector = new DenseVector(testArray);
            DenseVector result = +DenseVector;
            Assert.AreEqual(DenseVector.Count, result.Count);
            for (int i = 0; i < DenseVector.Count; i++)
            {
                Assert.AreEqual(+DenseVector[i], result[i]);
            }
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void DenseOperatorPlusNull()
        {
            DenseVector DenseVector = null;
            DenseVector = +DenseVector;
        }

        [Test]
        public void DenseOperatorMultiplyScalarVector()
        {
            DenseVector DenseVector = new DenseVector(testArray);
            double scalar = 2.2;
            DenseVector result = scalar * DenseVector;
            Assert.AreEqual(DenseVector.Count, result.Count);
            for (int i = 0; i < testArray.Length; i++)
            {
                Assert.AreEqual(scalar * testArray[i], result[i]);
            }
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void DenseOperatorMultiplyScalarVectorNull()
        {
            DenseVector DenseVector = null;
            double scalar = 2.2;
            DenseVector result = scalar * DenseVector;
        }

        [Test]
        public void DenseOperatorMultiplyVectorScalar()
        {
            DenseVector DenseVector = new DenseVector(testArray);
            double scalar = 2.2;
            DenseVector result = DenseVector * scalar;
            Assert.AreEqual(DenseVector.Count, result.Count);
            for (int i = 0; i < DenseVector.Count; i++)
            {
                Assert.AreEqual(DenseVector[i] * scalar, result[i]);
            }
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void DenseOperatorMultiplyVectorNullScalar()
        {
            DenseVector DenseVector = null;
            double scalar = 2.2;
            DenseVector result = DenseVector * scalar;
        }

        [Test]
        public void DenseOperatorMultiply()
        {
            DenseVector vector1 = new DenseVector(testArray);
            DenseVector vector2 = new DenseVector(testArray);
            Matrix result = vector1 * vector2;
            Assert.AreEqual(vector1.Count, result.Rows);
            Assert.AreEqual(vector2.Count, result.Columns);
            for (int i = 0; i < vector1.Count; i++)
            {
                for (int j = 0; j < vector2.Count; j++)
                {
                    Assert.AreEqual(vector1[i] * vector2[j], result[i, j]);
                }
            }
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void DenseOperatorMultiplyNull1()
        {
            DenseVector vector1 = new DenseVector(testArray);
            DenseVector vector2 = null;
            Matrix result = vector1 * vector2;
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void DenseOperatorMultiplyNull2()
        {
            DenseVector vector1 = null;
            DenseVector vector2 = new DenseVector(testArray);
            Matrix result = vector1 * vector2;
        }

        [Test]
        public void DenseOperatorDivide()
        {
            DenseVector DenseVector = new DenseVector(testArray);
            double scalar = 2.2;
            DenseVector result = DenseVector / scalar;
            Assert.AreEqual(DenseVector.Count, result.Count);
            for (int i = 0; i < DenseVector.Count; i++)
            {
                Assert.AreEqual(DenseVector[i] / scalar, result[i]);
            }
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void DenseOperatorDivideNull()
        {
            DenseVector DenseVector = null;
            double scalar = 2.2;
            DenseVector result = DenseVector / scalar;
        }
    }
}